package com.yiyuan.app.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.guaike.core.utils.UUIDUtil;
import com.yiyuan.app.config.WxPayProperties;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.AmountReq;
import com.wechat.pay.java.service.refund.model.CreateRequest;
import com.wechat.pay.java.service.refund.model.Refund;
import com.yiyuan.app.dao.*;
import com.yiyuan.app.entity.enums.*;
import com.yiyuan.app.entity.po.*;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
@AllArgsConstructor
public class BaseDealPayService {

    private final UAppUserEquityDAO uAppUserEquityDAO;
    private final UAppUserDAO uAppUserDAO;
    private final MConfVipDAO mConfVipDAO;
    private final DDetailsPineconeDAO dDetailsPineconeDAO;
    private final MRankRichDAO mRankRichDAO;
    private final BaseUtilService baseUtilService;
    private final MRecordTaskDailyDAO mRecordTaskDailyDAO;
    private final MRecordTaskDAO mRecordTaskDAO;
    private final MRecordPineDAO mRecordPineDAO;
    private final MRecordPineDetailDAO mRecordPineDetailDAO;
    private final MRecordSeriesRechargeDetailDAO mRecordSeriesRechargeDetailDAO;
    private final MRecordSeriesRechargeDAO mRecordSeriesRechargeDAO;
    private final DOrderRechargeDAO dOrderRechargeDAO;
    private final MProductSeriesRechargeBoxDAO mProductSeriesRechargeBoxDAO;
    private final MProductCardDetailDAO mProductCardDetailDAO;
    private final MRecordProductCardDAO mRecordProductCardDAO;
    private final UConfManageEquityDAO uConfManageEquityDAO;
    private final DDetailsOrderPrizeDAO dDetailsOrderPrizeDAO;
    private final GRecordGameDAO gRecordGameDAO;
    private final AlipayClient alipayClient;
    private final RefundService refundService;
    private final WxPayProperties properties;

    @Transactional
    public void dealOrder(DOrderRechargePO rechargePO) throws Exception {
        LocalDate today = LocalDate.now();
        UAppUserPO userPO = uAppUserDAO.findById(rechargePO.getUserId());
        UAppUserEquityPO userEquityPO = uAppUserEquityDAO.findByUserIdLock(rechargePO.getUserId());
        BigDecimal newRechargeMoney = userEquityPO.getRechargeMoney().add(rechargePO.getPayAmount());
        userEquityPO.setRechargeMoney(newRechargeMoney);
        MConfVipPO currentVip = mConfVipDAO.findOne(MConfVipPO::getVipLevel, userEquityPO.getVipGrade());
        MConfVipPO confVipPO = mConfVipDAO.checkVipNext(newRechargeMoney);
        Integer giveRate = confVipPO.getGiveRate();
        userEquityPO.setVipGrade(confVipPO.getVipLevel());
        if (OrderProductTypeEnum.lock_machine.getCode().equals(rechargePO.getProductType())) {
            JSONObject jsonObject = JSON.parseObject(rechargePO.getProductInfo());
            Long gameRecordId = jsonObject.getLong("gameRecordId");
            GRecordGamePO gamePO = gRecordGameDAO.findById(gameRecordId);
            String checkGaming = gamePO.getRoomId() + gamePO.getPositionNo();
            Boolean gaming = baseUtilService.checkGaming(checkGaming, userPO.getId(), gamePO.getRoomId(), gamePO.getPositionNo(), OrderProductTypeEnum.lock_machine.getCode(), jsonObject);
            if (!gaming) {
                this.refund(rechargePO);
                return;
            }
        } else if (OrderProductTypeEnum.forbid_look.getCode().equals(rechargePO.getProductType())) {
            JSONObject jsonObject = JSON.parseObject(rechargePO.getProductInfo());
            Long gameRecordId = jsonObject.getLong("gameRecordId");
            GRecordGamePO gamePO = gRecordGameDAO.findById(gameRecordId);
            String checkGaming = gamePO.getRoomId() + gamePO.getPositionNo();
            Boolean gaming = baseUtilService.checkGaming(checkGaming, userPO.getId(), gamePO.getRoomId(), gamePO.getPositionNo(), OrderProductTypeEnum.forbid_look.getCode(), jsonObject);
            if (!gaming) {
                this.refund(rechargePO);
                return;
            }
        } else if (OrderProductTypeEnum.occupy.getCode().equals(rechargePO.getProductType())) {
            JSONObject jsonObject = JSON.parseObject(rechargePO.getProductInfo());
            Integer pinecone = jsonObject.getInteger("pinecone");
            Integer prize = new BigDecimal(pinecone).multiply(new BigDecimal(giveRate)).divide(new BigDecimal(100), 0, BigDecimal.ROUND_UP).intValue();
            addPinePrizePinecone(today, userPO.getId(), prize);
            Long gameRecordId = jsonObject.getLong("gameRecordId");
            GRecordGamePO gamePO = gRecordGameDAO.findById(gameRecordId);
            String checkGaming = gamePO.getRoomId() + gamePO.getPositionNo();
            Boolean gaming = baseUtilService.checkGaming(checkGaming, userPO.getId(), gamePO.getRoomId(), gamePO.getPositionNo(), OrderProductTypeEnum.occupy.getCode(), jsonObject);
            if (!gaming) {
                this.refund(rechargePO);
                return;
            }
        } else if (OrderProductTypeEnum.series_recharge.getCode().equals(rechargePO.getProductType())) {
            JSONObject jsonObject = JSON.parseObject(rechargePO.getProductInfo());
            Integer seriesDays = jsonObject.getInteger("seriesDays");
            Integer pinecone = jsonObject.getInteger("pinecone");
            Integer prize = new BigDecimal(pinecone).multiply(new BigDecimal(giveRate)).divide(new BigDecimal(100), 0, BigDecimal.ROUND_UP).intValue();
            addPinePrizePinecone(today, userPO.getId(), prize);
            MRecordSeriesRechargePO seriesRechargePO;
            if (seriesDays == 1) {
                seriesRechargePO = new MRecordSeriesRechargePO();
                seriesRechargePO.setUserId(userPO.getId());
                seriesRechargePO.setRechargeDay(1);
                List<MProductSeriesRechargeBoxPO> boxPOS = mProductSeriesRechargeBoxDAO.findAll(MProductSeriesRechargeBoxPO::getSeriesDays, Boolean.TRUE);
                boxPOS.forEach(box -> {
                    if (box.getSeriesDays() == 3) {
                        seriesRechargePO.setThreePrize(box.getPinecone());
                        seriesRechargePO.setThreeStatus(TaskStatusEnum.go_complete.getCode());
                    } else if (box.getSeriesDays() == 5) {
                        seriesRechargePO.setFivePrize(box.getPinecone());
                        seriesRechargePO.setFiveStatus(TaskStatusEnum.go_complete.getCode());
                    } else if (box.getSeriesDays() == 7) {
                        seriesRechargePO.setSevenPrize(box.getPinecone());
                        seriesRechargePO.setSevenStatus(TaskStatusEnum.go_complete.getCode());
                    }
                });
                mRecordSeriesRechargeDAO.save(seriesRechargePO);
            } else {
                Long recordRechargeId = jsonObject.getLong("recordRechargeId");
                seriesRechargePO = mRecordSeriesRechargeDAO.findById(recordRechargeId);
                if (seriesDays >= 3 && seriesRechargePO.getThreeStatus().equals(TaskStatusEnum.go_complete.getCode())) {
                    seriesRechargePO.setThreeStatus(TaskStatusEnum.unclaimed.getCode());
                }
                if (seriesDays >= 5 && seriesRechargePO.getFiveStatus().equals(TaskStatusEnum.go_complete.getCode())) {
                    seriesRechargePO.setFiveStatus(TaskStatusEnum.unclaimed.getCode());
                }
                if (seriesDays >= 7 && seriesRechargePO.getSevenStatus().equals(TaskStatusEnum.go_complete.getCode())) {
                    seriesRechargePO.setSevenStatus(TaskStatusEnum.unclaimed.getCode());
                }
                mRecordSeriesRechargeDAO.updateById(seriesRechargePO);
            }
            MRecordSeriesRechargeDetailPO detailPO = new MRecordSeriesRechargeDetailPO();
            detailPO.setRecordRechargeId(seriesRechargePO.getId());
            detailPO.setUserId(userPO.getId());
            detailPO.setRechargeDay(seriesDays);
            detailPO.setMoney(rechargePO.getPayAmount());
            detailPO.setPinecone(pinecone);
            mRecordSeriesRechargeDetailDAO.save(detailPO);
            DDetailsPineconePO myDetail = new DDetailsPineconePO();
            myDetail.setUserId(userPO.getId());
            myDetail.setLabelType(LabelTypeEnum.recharge.getCode());
            myDetail.setDetailsType(DetailsTypeEnum.income.getCode());
            myDetail.setPinecone(pinecone);
            myDetail.setRemark("连续充值第" + seriesDays + "天");
            dDetailsPineconeDAO.save(myDetail);
            userEquityPO.setPinecone(Math.addExact(userEquityPO.getPinecone(), pinecone));
        } else if (OrderProductTypeEnum.novice_gift_pack.getCode().equals(rechargePO.getProductType())) {
            JSONObject jsonObject = JSON.parseObject(rechargePO.getProductInfo());
            Integer pinecone = jsonObject.getInteger("pinecone");
            Integer prize = new BigDecimal(pinecone).multiply(new BigDecimal(giveRate)).divide(new BigDecimal(100), 0, BigDecimal.ROUND_UP).intValue();
            addPinePrizePinecone(today, userPO.getId(), prize);
            DDetailsPineconePO myDetail = new DDetailsPineconePO();
            myDetail.setUserId(userPO.getId());
            myDetail.setLabelType(LabelTypeEnum.recharge.getCode());
            myDetail.setDetailsType(DetailsTypeEnum.income.getCode());
            myDetail.setPinecone(pinecone);
            myDetail.setRemark("新手大礼包");
            dDetailsPineconeDAO.save(myDetail);
            userEquityPO.setPinecone(Math.addExact(userEquityPO.getPinecone(), pinecone));
        } else if (OrderProductTypeEnum.activity_pack.getCode().equals(rechargePO.getProductType())) {
            JSONObject jsonObject = JSON.parseObject(rechargePO.getProductInfo());
            Integer pinecone = jsonObject.getInteger("pinecone");
            Integer prize = new BigDecimal(pinecone).multiply(new BigDecimal(giveRate)).divide(new BigDecimal(100), 0, BigDecimal.ROUND_UP).intValue();
            addPinePrizePinecone(today, userPO.getId(), prize);
            DDetailsPineconePO myDetail = new DDetailsPineconePO();
            myDetail.setUserId(userPO.getId());
            myDetail.setLabelType(LabelTypeEnum.recharge.getCode());
            myDetail.setDetailsType(DetailsTypeEnum.income.getCode());
            myDetail.setPinecone(pinecone);
            myDetail.setRemark("活动大礼包");
            dDetailsPineconeDAO.save(myDetail);
            userEquityPO.setPinecone(Math.addExact(userEquityPO.getPinecone(), pinecone));
        } else if (OrderProductTypeEnum.recharge_activity.getCode().equals(rechargePO.getProductType())) {
            JSONObject jsonObject = JSON.parseObject(rechargePO.getProductInfo());
            Integer pinecone = jsonObject.getInteger("pinecone");
            Integer prize = new BigDecimal(pinecone).multiply(new BigDecimal(giveRate)).divide(new BigDecimal(100), 0, BigDecimal.ROUND_UP).intValue();
            addPinePrizePinecone(today, userPO.getId(), prize);
            DDetailsPineconePO myDetail = new DDetailsPineconePO();
            myDetail.setUserId(userPO.getId());
            myDetail.setLabelType(LabelTypeEnum.recharge.getCode());
            myDetail.setDetailsType(DetailsTypeEnum.income.getCode());
            myDetail.setPinecone(pinecone);
            myDetail.setRemark("充值活动");
            dDetailsPineconeDAO.save(myDetail);
            userEquityPO.setPinecone(Math.addExact(userEquityPO.getPinecone(), pinecone));
        } else if (OrderProductTypeEnum.month_card.getCode().equals(rechargePO.getProductType())) {
            JSONObject jsonObject = JSON.parseObject(rechargePO.getProductInfo());
            Integer directlyPinecone = jsonObject.getInteger("directlyPinecone");
            Integer dailyPinecone = jsonObject.getInteger("dailyPinecone");
            Integer days = jsonObject.getInteger("days");
            int pinecone = dailyPinecone * days + directlyPinecone;
            Integer prize = new BigDecimal(pinecone).multiply(new BigDecimal(giveRate)).divide(new BigDecimal(100), 0, BigDecimal.ROUND_UP).intValue();
            addPinePrizePinecone(today, userPO.getId(), prize);
            DDetailsPineconePO myDetail = new DDetailsPineconePO();
            myDetail.setUserId(userPO.getId());
            myDetail.setLabelType(LabelTypeEnum.month_card.getCode());
            myDetail.setDetailsType(DetailsTypeEnum.income.getCode());
            myDetail.setPinecone(directlyPinecone);
            myDetail.setRemark("月卡立即获得");
            dDetailsPineconeDAO.save(myDetail);
            userEquityPO.setPinecone(Math.addExact(userEquityPO.getPinecone(), directlyPinecone));
            MProductCardDetailPO detailPO = mProductCardDetailDAO.findById(rechargePO.getProductId());
            MRecordProductCardPO cardPO = mRecordProductCardDAO.findUserCardByCardId(userPO.getId(), detailPO.getId());
            if (Objects.isNull(cardPO)) {
                cardPO = new MRecordProductCardPO();
                cardPO.setUserId(userPO.getId());
                cardPO.setCardId(detailPO.getId());
                cardPO.setCardType(CardTypeEnum.month_card.getCode());
                cardPO.setRemainDay(days);
                cardPO.setCardName(detailPO.getCardName());
                cardPO.setDirectlyPinecone(directlyPinecone);
                cardPO.setDailyPinecone(dailyPinecone);
                cardPO.setMoney(rechargePO.getPayAmount());
                cardPO.setImage(detailPO.getImage());
                mRecordProductCardDAO.save(cardPO);
            } else {
                cardPO.setRemainDay(Math.addExact(cardPO.getRemainDay(), days));
                cardPO.setCardName(detailPO.getCardName());
                cardPO.setDirectlyPinecone(directlyPinecone);
                cardPO.setDailyPinecone(dailyPinecone);
                cardPO.setMoney(rechargePO.getPayAmount());
                cardPO.setImage(detailPO.getImage());
                mRecordProductCardDAO.updateById(cardPO);
            }
        } else if (OrderProductTypeEnum.week_card.getCode().equals(rechargePO.getProductType())) {
            JSONObject jsonObject = JSON.parseObject(rechargePO.getProductInfo());
            Integer directlyPinecone = jsonObject.getInteger("directlyPinecone");
            Integer dailyPinecone = jsonObject.getInteger("dailyPinecone");
            Integer days = jsonObject.getInteger("days");
            int pinecone = dailyPinecone * days + directlyPinecone;
            Integer prize = new BigDecimal(pinecone).multiply(new BigDecimal(giveRate)).divide(new BigDecimal(100), 0, BigDecimal.ROUND_UP).intValue();
            addPinePrizePinecone(today, userPO.getId(), prize);
            DDetailsPineconePO myDetail = new DDetailsPineconePO();
            myDetail.setUserId(userPO.getId());
            myDetail.setLabelType(LabelTypeEnum.week_card.getCode());
            myDetail.setDetailsType(DetailsTypeEnum.income.getCode());
            myDetail.setPinecone(directlyPinecone);
            myDetail.setRemark("周卡立即获得");
            dDetailsPineconeDAO.save(myDetail);
            userEquityPO.setPinecone(Math.addExact(userEquityPO.getPinecone(), directlyPinecone));
            MProductCardDetailPO detailPO = mProductCardDetailDAO.findById(rechargePO.getProductId());
            MRecordProductCardPO cardPO = mRecordProductCardDAO.findUserCardByCardId(userPO.getId(), detailPO.getId());
            if (Objects.isNull(cardPO)) {
                cardPO = new MRecordProductCardPO();
                cardPO.setUserId(userPO.getId());
                cardPO.setCardId(detailPO.getId());
                cardPO.setCardType(CardTypeEnum.week_card.getCode());
                cardPO.setRemainDay(days);
                cardPO.setCardName(detailPO.getCardName());
                cardPO.setDirectlyPinecone(directlyPinecone);
                cardPO.setDailyPinecone(dailyPinecone);
                cardPO.setMoney(rechargePO.getPayAmount());
                cardPO.setImage(detailPO.getImage());
                mRecordProductCardDAO.save(cardPO);
            } else {
                cardPO.setRemainDay(Math.addExact(cardPO.getRemainDay(), days));
                cardPO.setCardName(detailPO.getCardName());
                cardPO.setDirectlyPinecone(directlyPinecone);
                cardPO.setDailyPinecone(dailyPinecone);
                cardPO.setMoney(rechargePO.getPayAmount());
                cardPO.setImage(detailPO.getImage());
                mRecordProductCardDAO.updateById(cardPO);
            }
        }
        //判断vip是否升级
        if (currentVip.getVipLevel() < confVipPO.getVipLevel()) {
            List<MConfVipPO> vips = mConfVipDAO.findConfigBetweenVips(currentVip.getVipLevel(), confVipPO.getVipLevel());
            int pinecone = vips.stream().mapToInt(MConfVipPO::getPinecone).sum();
            userEquityPO.setPinecone(Math.addExact(userEquityPO.getPinecone(), pinecone));
            DDetailsPineconePO myDetail = new DDetailsPineconePO();
            myDetail.setUserId(rechargePO.getUserId());
            myDetail.setLabelType(LabelTypeEnum.upgrade.getCode());
            myDetail.setDetailsType(DetailsTypeEnum.income.getCode());
            myDetail.setPinecone(pinecone);
            dDetailsPineconeDAO.save(myDetail);
            userEquityPO.setForbidLookThirty(Math.addExact(userEquityPO.getForbidLookThirty(), Math.subtractExact(confVipPO.getUnalowLookNum(), currentVip.getUnalowLookNum())));
            userEquityPO.setLockFifteen(Math.addExact(userEquityPO.getLockFifteen(), Math.subtractExact(confVipPO.getLock15Num(), currentVip.getLock15Num())));
            userEquityPO.setLockThirty(Math.addExact(userEquityPO.getLockThirty(), Math.subtractExact(confVipPO.getLock30Num(), currentVip.getLock30Num())));
            userEquityPO.setLockSixty(Math.addExact(userEquityPO.getLockSixty(), Math.subtractExact(confVipPO.getLock60Num(), currentVip.getLock60Num())));
        }
        // 添加财富榜
        MRankRichPO richPO = mRankRichDAO.findUserRank(LocalDate.now(), rechargePO.getUserId());
        if (Objects.isNull(richPO)) {
            richPO = new MRankRichPO();
            richPO.setUserId(userPO.getId());
            richPO.setAvatarurl(userPO.getAvatarurl());
            richPO.setNickname(userPO.getNickname());
            richPO.setVipGrade(userEquityPO.getVipGrade());
            richPO.setRechargeMoney(rechargePO.getPayAmount());
            richPO.setRankDate(today);
            mRankRichDAO.save(richPO);
        } else {
            richPO.setAvatarurl(userPO.getAvatarurl());
            richPO.setNickname(userPO.getNickname());
            richPO.setVipGrade(userEquityPO.getVipGrade());
            richPO.setRechargeMoney(richPO.getRechargeMoney().add(rechargePO.getPayAmount()));
            mRankRichDAO.updateById(richPO);
        }
        // 处理每日任务和长期任务中充值相关任务
        String dailyKey = userPO.getId() + today.toString() + "dailyTask";
        baseUtilService.setDailyTask(dailyKey, userPO.getId(), today);
        mRecordTaskDailyDAO.updateFirstRecharge(userPO.getId(), today);
        List<MRecordTaskDailyPO> list = mRecordTaskDailyDAO.findUserTodayAction(userPO.getId(), today, DailyTaskActionEnum.total_recharge.getCode());
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(po -> {
                po.setCurrentProgress(Math.addExact(po.getCurrentProgress(), rechargePO.getPayAmount().multiply(new BigDecimal(100)).intValue()));
                if (po.getCurrentProgress().compareTo(po.getThreshold() * 100) >= 0 && po.getStatus().equals(TaskStatusEnum.go_complete.getCode())) {
                    po.setStatus(TaskStatusEnum.unclaimed.getCode());
                }
            });
            mRecordTaskDailyDAO.updateBatchById(list);
        }
        baseUtilService.dealDailyTaskAllComplete(userPO.getId(), today);
        String key = userPO.getId() + today.toString() + "task";
        baseUtilService.setTask(key, userPO.getId());
        List<MRecordTaskPO> pos = mRecordTaskDAO.findList(userPO.getId(), TaskActionEnum.total_recharge.getCode(), Collections.singletonList(TaskStatusEnum.go_complete.getCode()));
        if (CollectionUtils.isNotEmpty(pos)) {
            pos.forEach(po -> {
                po.setCurrentProgress(Math.addExact(po.getCurrentProgress(), rechargePO.getPayAmount().multiply(new BigDecimal(100)).intValue()));
                if (po.getCurrentProgress().compareTo(po.getThreshold() * 100) >= 0) {
                    po.setStatus(TaskStatusEnum.unclaimed.getCode());
                }
            });
            mRecordTaskDAO.updateBatchById(pos);
        }
        // 更新用户特权
        uAppUserEquityDAO.updateById(userEquityPO);
        // 进行管理员分佣
        if (Objects.nonNull(userPO.getInviterId())) {
            UAppUserPO appUserPO = uAppUserDAO.findById(userPO.getInviterId());
            if (appUserPO.getIsManage()) {
                int month = (int) ChronoUnit.MONTHS.between(today.withDayOfMonth(1), userPO.getInviterDate().withDayOfMonth(1)) + 1;
                UConfManageEquityPO po = uConfManageEquityDAO.findUserOne(appUserPO.getId(), month);
                if (Objects.nonNull(po)) {
                    BigDecimal prize = rechargePO.getPayAmount().multiply(po.getPrizeRatio()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_UP);
                    uAppUserEquityDAO.addManageMoney(appUserPO.getId(), prize);
                    DDetailsOrderPrizePO prizePO = new DDetailsOrderPrizePO();
                    prizePO.setUserId(userPO.getId());
                    prizePO.setManageId(appUserPO.getId());
                    prizePO.setOrderNumber(rechargePO.getOrderNumber());
                    prizePO.setPayAmount(rechargePO.getPayAmount());
                    prizePO.setPrizeMoney(prize);
                    prizePO.setPrizeRatio(po.getPrizeRatio());
                    prizePO.setPrizeType(MoneyTypeEnum.income.getCode());
                    prizePO.setRemark("受邀第" + month + "个月购买" + OrderProductTypeEnum.getByCode(rechargePO.getProductType()).getDesc());
                    dDetailsOrderPrizeDAO.save(prizePO);
                }
            }
        }
    }


    private void addPinePrizePinecone(LocalDate today, Long userId, Integer pinecone) {
        LocalDate startOfWeek = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
        LocalDate endOfWeek = today.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
        Long pineId = baseUtilService.getUserPine(userId, startOfWeek, endOfWeek);
        mRecordPineDAO.addPinecone(pineId, pinecone);
        MRecordPineDetailPO detailPO = new MRecordPineDetailPO();
        detailPO.setRecordPineId(pineId);
        detailPO.setGetPinecone(pinecone);
        mRecordPineDetailDAO.save(detailPO);
    }

    private void refund(DOrderRechargePO rechargePO) throws AlipayApiException {
        String refundNo = UUIDUtil.createOrderNo();
        String reason = "锁机房间被占用退款";
        rechargePO.setRefundOrderNumber(refundNo);
        rechargePO.setStatus(OrderStatusEnum.refunding.getCode());
        if (rechargePO.getPayType().equals(PayTypeEnum.wx.getCode())) {
            this.wxRefund(rechargePO, reason);
        } else if (rechargePO.getPayType().equals(PayTypeEnum.ali.getCode())) {
            AlipayTradeRefundResponse response = this.aliRefund(rechargePO, reason);
            if (response.isSuccess()) {
                rechargePO.setStatus(OrderStatusEnum.refund_success.getCode());
            } else {
                rechargePO.setStatus(OrderStatusEnum.refund_fail.getCode());
                rechargePO.setRefundFailReason(response.getSubMsg());
            }
        } else if (rechargePO.getPayType().equals(PayTypeEnum.ios.getCode())) {
            //todo ios退款
        }
        dOrderRechargeDAO.updateById(rechargePO);
    }

    private Refund wxRefund(DOrderRechargePO rechargePO, String refundReason) {
        CreateRequest request = new CreateRequest();
        AmountReq amount = new AmountReq();
        amount.setRefund(rechargePO.getPayAmount().multiply(new BigDecimal(100)).longValue());
        amount.setTotal(rechargePO.getPayAmount().multiply(new BigDecimal(100)).longValue());
        amount.setCurrency("CNY");
        request.setAmount(amount);
        request.setTransactionId(rechargePO.getOutTradeNo());
        request.setOutTradeNo(rechargePO.getOrderNumber());
        request.setOutRefundNo(rechargePO.getRefundOrderNumber());
        request.setNotifyUrl(properties.getRefundCallBackUrl());
        request.setReason(refundReason);
        Refund refund = refundService.create(request);
        log.info("微信退款返回结果，{}", JSON.toJSONString(refund));
        return refund;
    }

    private AlipayTradeRefundResponse aliRefund(DOrderRechargePO rechargePO, String refundReason) throws AlipayApiException {
        // 构造请求参数以调用接口
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        AlipayTradeRefundModel model = new AlipayTradeRefundModel();
        // 设置商户订单号
        model.setOutTradeNo(rechargePO.getOrderNumber());
        // 设置支付宝交易号
        model.setTradeNo(rechargePO.getOutTradeNo());
        // 设置退款金额
        model.setRefundAmount(rechargePO.getPayAmount().toPlainString());
        // 设置退款原因说明
        model.setRefundReason(refundReason);
        // 设置退款请求号
        model.setOutRequestNo(rechargePO.getRefundOrderNumber());
        request.setBizModel(model);
        // 第三方代调用模式下请设置app_auth_token
        // request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->");
        AlipayTradeRefundResponse response = alipayClient.execute(request);
        log.info("支付宝退款返回结果，{}", response.getBody());
        return response;
    }
}
